use std::fs;

pub struct Config {
    pub query: String,
    pub filename: String,
    pub case_insensitive: bool,
}

impl Config {
    pub fn new(args: &[String]) -> Result<Config, &'static str> {
        if args.len() < 3 {
            return Err("Not enough arguments");
        }
        let query = args[1].clone();
        let filename = args[2].clone();
        let case_insensitive = args.len() == 4;
        Ok(Config { query, filename, case_insensitive })
    }
}

pub fn search(config: Config) -> Result<(), std::io::Error> {
    println!("Searching for: {}", config.query);
    println!("In file: {}", config.filename);

    let contents = fs::read_to_string(config.filename);
    if let Err(err) = contents {
        return Err(err);
    }
    else {
        let contents = contents.unwrap();
        let mut count = 0;
        for line in contents.lines() {
            if config.case_insensitive {
                if line.to_lowercase().contains(config.query.to_lowercase().as_str()) {
                    count += 1;
                    println!("{}", line);
                }
            }
            else {
                if line.contains(config.query.as_str()) {
                    count += 1;
                    println!("{}", line);
                }
            }
        }

        println!("{} matches found", count);
    }
    Ok(())
}

pub fn run(config: Config) -> Result<(), std::io::Error>{
    search(config)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_config_new() {
        let args = vec!["minigrep".to_string(), "foo".to_string(), "test.txt".to_string()];
        let config = Config::new(&args).unwrap();
        assert_eq!(config.query, "foo");
        assert_eq!(config.filename, "test.txt");
    }

    #[test]
    fn test_config_new_err() {
        let args = vec!["minigrep".to_string()];
        let config = Config::new(&args);
        assert!(config.is_err());
    }

    #[test]
    fn test_run_err() {
        let args = vec!["minigrep".to_string(), "foo".to_string(), "test.txt".to_string()];
        let config = Config::new(&args).unwrap();
        run(config).unwrap_err();
    }

    #[test]
    fn test_run() {
        let args = vec!["minigrep.exe".to_string(), "the".to_string(), "poem.txt".to_string()];
        let config = Config::new(&args).unwrap();
        run(config).unwrap();
    }
}